`timescale 1ns / 1ps
/************************************************************\
 **  Copyright (c) 2022-2023 Gonsin, Inc.
 **  All Right Reserved.
 **  Author: http://www.anlogic.com/
 **  Description: axi_master_cfg
 **  Rev 1.0
\************************************************************/

module axi_master_cfg #(
parameter TX_CFG = {24'b0,1'b0,7'b0101010},
parameter RX_CFG = {24'b0,8'b00101010},
parameter PAUSE_SRCAD_CFG	= 48'h5af1f2f3f4f5,  	//暂停帧 mac源地址:48'h5af1f2f3f4f5,
parameter SPEED_CFG	= {30'b0,2'b10},
parameter FLOW_CTRL_CFG	= {30'b0,2'b00},
parameter AD_FILTER_MODE_CFG = {31'b0,1'b0},		//1'b1：启用混杂模式  1'b0：启用地址过滤模式,
parameter UNICAST_AD_CFG = 48'h0605040302DA,
parameter AD_TABLE0_CFG = 48'h06050403020A,
parameter AD_TABLE1_CFG = 48'h16151413121A,
parameter AD_TABLE2_CFG = 48'h26252423222A,
parameter AD_TABLE3_CFG = 48'h36353433323A,
parameter AD_TABLE4_CFG = 48'h46454443424A,
parameter AD_TABLE5_CFG = 48'h56555453525A,
parameter AD_TABLE6_CFG = 48'h66656463626A,
parameter AD_TABLE7_CFG = 48'h76757473727A,
parameter AD_TABLE8_CFG = 48'h86858483828A,
parameter AD_TABLE9_CFG = 48'h96959493929A,
parameter AD_TABLE10_CFG = 48'hA6A5A4A3A2AA,
parameter AD_TABLE11_CFG = 48'hB6B5B4B3B2BA,
parameter AD_TABLE12_CFG = 48'hC6C5C4C3C2CA,
parameter AD_TABLE13_CFG = 48'hD6D5D4D3D2DA,
parameter AD_TABLE14_CFG = 48'hE6E5E4E3E2EA,
parameter AD_TABLE15_CFG = 48'hF6F5F4F3F2FA,
parameter MDIO_CLK_CFG = {25'b0,7'b1001001},  		// mdc = mAXI_aclk_i/(9+1)*2=50/20=2.5MHZ
parameter MDIO_WE1_DATA_CFG	= {16'h0,16'h9340},		//PHY芯片地址：phy_A:5'b00010  phy_B:5'b00001   对PHY仅配置基本模式控制寄存器（0x00/5'h00）即可:双工/速度配置
parameter MDIO_WE1_CTRL_CFG	= {19'b0,5'b00000,5'b00001,2'b01,1'b1},  //16'h9340： 千兆全双工 ； 16'hb300：百兆全双工；  16'h9300：十兆全双工
parameter MDIO_RD1_CTRL_CFG	= {19'b0,5'b00000,5'b00001,2'b10,1'b1}   //16'h9240：千兆半双工（核不支持）；16'hb200：百兆半双工；  16'h9200：十兆半双工 
)
(	
input wire init_AXItxn_i,  		// (initiate)发起AXI事务
output wire mAXI_txnDone_o,  	// AXI事务完成时断言
//AXI总线
input wire mAXI_aclk_i,
input wire mAXI_areset_i,
output wire [7:0] mAXI8b_awaddr_o,
output wire mAXI_awvalid_o,
input wire mAXI_awready_i,
output wire [31:0] mAXI32b_wdata_o,   
output wire mAXI_wvalid_o,
input wire mAXI_wready_i,
input wire [1:0] mAXI2b_bresp_i,
input wire mAXI_bvalid_i,
output wire mAXI_bready_o,
output wire [7:0] mAXI8b_araddr_o,
output wire mAXI_arvalid_o,
input wire mAXI_arready_i,
input wire [31:0] mAXI32b_rdata_i,
input wire [1:0] mAXI2b_rresp_i,
input wire mAXI_rvalid_i,
output wire mAXI_rready_o
);
    
//----------------------------------------------------------------------------
// 模块内部信号
//----------------------------------------------------------------------------
// 读写事务次数
localparam WE_TRANSACTIONS_NUM = 6'h2D;  // WE_TRANSACTIONS_NUM 值比 #337行 case(write6b_index)最大值加1
localparam RD_TRANSACTIONS_NUM = 6'h13;  // RD_TRANSACTIONS_NUM 值比 #530行 case(read6b_index) 最大值加1
//地址参数
localparam TX_ADDRESS	= 8'h10;
localparam RX_ADDRESS = 8'h20;
localparam PAUSE_SRCAD0_ADDRESS = 8'h30;
localparam PAUSE_SRCAD1_ADDRESS	= 8'h40;
localparam SPEED_ADDRESS = 8'h50;
localparam FLOW_CTRL_ADDRESS = 8'h60;
localparam AD_FILTER_MODE_ADDRESS	= 8'h70;
localparam UNICAST_AD0_ADDRESS = 8'h80;
localparam UNICAST_AD1_ADDRESS = 8'h82;
localparam AD_TABLE0_ADDRESS = 8'h84;
localparam AD_TABLE1_ADDRESS = 8'h86;
localparam MDIO_CLK_ADDRESS = 8'h90;
localparam MDIO_CTRL_ADDRESS = 8'hA0;
localparam MDIO_RD_DATA_ADDRESS	= 8'hB0;
localparam MDIO_WE_DATA_ADDRESS	= 8'hC0;
  
localparam [1:0] IDLE = 2'b00; 				// 当INIT_AXI_TXN上有0到1的转换时，当前状态机跳转为INIT_WRITE，INIT_WRITE此状态启动AXI4Lite写事务
localparam [1:0] INIT_WRITE = 2'b01; 	// 此状态初始化写事务，一旦完成写，状态机将状态更改为INIT_READ
localparam [1:0] INIT_READ = 2'b10; 	// 此状态初始化读取事务，读取完成
  
//AXI总线8个输出信号寄存器 
reg [7:0] axi8b_awaddr;
reg axi_awvalid;
reg [31:0] axi32b_wdata;
reg axi_wvalid;
reg axi_bready;
reg [7:0] axi8b_araddr;
reg axi_arvalid;
reg axi_rready;

//中间信号
reg [1:0] master2b_state;
reg init_txn_ff;
reg init_txn_ff2;
reg start_single_write;
reg [5:0] write6b_index;
reg start_single_read;
reg [5:0] read6b_index;
reg write_issued;
reg read_issued;
reg last_write;
reg last_read;
reg writes_done;
reg reads_done;
reg axi_txn_done_reg; 			/*synthesis keep=true*/
reg [31:0] rd32b_data_val;  /*synthesis keep=true*/
	
//----------------------------------------------------------------------------
// i/o connections assignments（axi4-lite总线 8个输出信号）
//----------------------------------------------------------------------------
assign mAXI8b_awaddr_o = axi8b_awaddr; 
assign mAXI_awvalid_o = axi_awvalid;
assign mAXI32b_wdata_o = axi32b_wdata;  
assign mAXI_wvalid_o = axi_wvalid; 
assign mAXI_bready_o = axi_bready; 
assign mAXI8b_araddr_o = axi8b_araddr; 
assign mAXI_arvalid_o = axi_arvalid;
assign mAXI_rready_o = axi_rready; 
assign mAXI_txnDone_o = axi_txn_done_reg; 
    
//----------------------------------------------------------------------------
// (initiate)发起AXI事务.启动标志信号产生逻辑
//---------------------------------------------------------------
  	
//产生一个脉冲以启动AXI事务。
always@(posedge mAXI_aclk_i)	begin                                                                        
	// Initiates AXI transaction delay    
	if(mAXI_areset_i == 1) begin                                                                    
		init_txn_ff <= 1'b0;                                                   
		init_txn_ff2 <= 1'b0;     
	end                                                                               
	else begin  
		init_txn_ff <= init_AXItxn_i;
		init_txn_ff2 <= init_txn_ff;                                                                 
	end                                                                      
end 
	
assign init_txn_pulse	= (!init_txn_ff2) && init_txn_ff;   //上升沿
  
//=======================================================================
// 写时序
//======================================================================= 
//--------------------
//写地址通道
//--------------------

// 写地址通道的目的是为整个事务请求地址和命令信息。 

// 请注意，在此示例中，axi_awvalid / axi_wvalid是在同一时间声明的，然后彼此独立解除声明。
// 在链路伙伴接收之前，AXI的VALID信号必须保持有效状态。

always@(posedge mAXI_aclk_i) begin                                                                          
	if(mAXI_areset_i == 1 || init_txn_pulse == 1'b1) begin                                                                    
		axi_awvalid <= 1'b0;                                                   
	end                                                                      
	//表示用户逻辑可用新的地址/数据命令           
	else begin                                                                    
	  if(start_single_write) begin                                                                
			axi_awvalid <= 1'b1;                                               
		end                                                                  
		//地址由互连从机接收（从机发出m_axi_awready）
		else if(mAXI_awready_i && axi_awvalid) begin                                                                
			axi_awvalid <= 1'b0;                                               
		end                                                                  
	end                                                                      
end 
	
// start_single_write触发新的写入事务。  
// write_index是一个计数器，用于跟踪 已发出/已启动 的写事务的数量                                                         
always@(posedge mAXI_aclk_i) begin                                                                        
	if(mAXI_areset_i == 1 || init_txn_pulse == 1'b1) begin                                                                    
		write6b_index <= 0;                                                      
	end                                                                      
	// 表示新的 写地址/写数据 ，可由用户逻辑提供                                               
	else if(start_single_write) begin                                                                    
		write6b_index <= write6b_index + 1;                                        
	end                                                                      
end 
      
//-------------------------------
//写数据通道：axi_wvalid信号
//------------------------------

// 写数据通道用于传输实际数据。  
// 数据生成特定于示例设计，下面显示 valid / wready 握手

always@(posedge mAXI_aclk_i) begin                                                                         
	if(mAXI_areset_i == 1  || init_txn_pulse == 1'b1) begin                                                                     
			axi_wvalid <= 1'b0;                                                     
	end                                                                       
	//通过用户逻辑给新的地址/数据命令发送信号              
	else if(start_single_write) begin                                                                     
		axi_wvalid <= 1'b1;                                                     
	end                                                                       
	//数据被互连从设备接受（从设备发出m_axi_wready）      
	else if(mAXI_wready_i && axi_wvalid) begin                                                                     
		axi_wvalid <= 1'b0;                                                      
	end                                                                       
end
	
//--------------------------------------------------
//写数据通道：用户逻辑（写 地址/数据 激励）
//--------------------------------------------------
/*  配置值									配置地址
    TX_CFG	         			TX_ADDRESS 						= 8'h10
    RX_CFG	              RX_ADDRESS 						= 8'h20
    PAUSE_SRCAD_CFG	      PAUSE_SRCAD0_ADDRESS 	= 8'h30
    SPEED_CFG	            PAUSE_SRCAD1_ADDRESS 	= 8'h40
    FLOW_CTRL_CFG	        SPEED_ADDRESS 				= 8'h50
    AD_FILTER_MODE_CFG    FLOW_CTRL_ADDRESS 		= 8'h60
    UNICAST_AD_CFG	      AD_FILTER_MODE_ADDRESS= 8'h70
    AD_TABLE3_CFG	        UNICAST_AD0_ADDRESS 	= 8'h80	
    AD_TABLE2_CFG	        UNICAST_AD1_ADDRESS 	= 8'h82	
    AD_TABLE1_CFG	        AD_TABLE0_ADDRESS 		= 8'h84
    AD_TABLE0_CFG	        AD_TABLE1_ADDRESS 		= 8'h86
    MDIO_CLK_CFG	        MDIO_CLK_ADDRESS 			= 8'h90
    MDIO_WE1_CTRL_CFG	    MDIO_CTRL_ADDRESS 		= 8'hA0
    MDIO_WE1_DATA_CFG	    MDIO_RD_DATA_ADDRESS 	= 8'hB0
    MDIO_RD1_CTRL_CFG     MDIO_WE_DATA_ADDRESS 	= 8'hC0
*/
    
// 根据需要针对不同的地址模式修改它们

//write addresses                                        
always@(posedge mAXI_aclk_i) begin                                                     
	if(mAXI_areset_i == 1  || init_txn_pulse == 1'b1) begin                                                 
		axi8b_awaddr <= SPEED_ADDRESS;    
		axi32b_wdata  <= SPEED_CFG;   //开始数据值为速度配置
	end                                                   
	// 表示新的写地址/写数据可由用户逻辑//提供                            
	//else if(mAXI_awready_i && axi_awvalid) 
	else if(mAXI_bvalid_i) begin 
		case(write6b_index)
			//6'h00:  begin
			// axi8b_awaddr <= SPEED_ADDRESS; 
			// axi32b_wdata  <= SPEED_CFG; 
			// end
			6'h01: begin
				axi8b_awaddr <= TX_ADDRESS; 
				axi32b_wdata  <= TX_CFG; 
			end
			6'h02: begin
				axi8b_awaddr <= RX_ADDRESS; 
				axi32b_wdata  <= RX_CFG; 
			end
			6'h03: begin
				axi8b_awaddr <= PAUSE_SRCAD0_ADDRESS; 
				axi32b_wdata  <= PAUSE_SRCAD_CFG[31:0]; 
			end
			6'h04: begin
				axi8b_awaddr <= PAUSE_SRCAD1_ADDRESS; 
				axi32b_wdata  <= {16'h0,PAUSE_SRCAD_CFG[47:32]}; 
			end
			6'h05: begin
				axi8b_awaddr <= FLOW_CTRL_ADDRESS; 
				axi32b_wdata  <= FLOW_CTRL_CFG; 
			end
			6'h06: begin
				axi8b_awaddr <= AD_FILTER_MODE_ADDRESS; 
				axi32b_wdata  <= AD_FILTER_MODE_CFG; 
			end
			6'h07: begin
				axi8b_awaddr <= UNICAST_AD0_ADDRESS; 
				axi32b_wdata  <= UNICAST_AD_CFG[31:0]; 
			end
			6'h08: begin
			  axi8b_awaddr <= UNICAST_AD1_ADDRESS; 
			  axi32b_wdata  <= {16'h0,UNICAST_AD_CFG[47:32]}; 
			end
			6'h09: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'hf,AD_TABLE15_CFG[47:32]}; 
			end
			6'h0A: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE15_CFG[31:0]; 
			end
			6'h0B: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'he,AD_TABLE14_CFG[47:32]}; 
			end
			6'h0C: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE14_CFG[31:0]; 
			end
			6'h0D: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'hd,AD_TABLE13_CFG[47:32]}; 
			end
			6'h0E: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
			  axi32b_wdata  <= AD_TABLE13_CFG[31:0]; 
			end
			6'h0F: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'hc,AD_TABLE12_CFG[47:32]}; 
			end
			6'h10: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE12_CFG[31:0]; 
			end
			6'h11: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'hb,AD_TABLE11_CFG[47:32]}; 
			end
			6'h12: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE11_CFG[31:0]; 
			end
			6'h13: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'ha,AD_TABLE10_CFG[47:32]}; 
			end
			6'h14: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE10_CFG[31:0]; 
			end
			6'h15: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h9,AD_TABLE9_CFG[47:32]}; 
			end
			6'h16: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE9_CFG[31:0]; 
			end
			6'h17: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h8,AD_TABLE8_CFG[47:32]}; 
			end
			6'h18: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE8_CFG[31:0]; 
			end
			6'h19: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h7,AD_TABLE7_CFG[47:32]}; 
			end
			6'h1A: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE7_CFG[31:0]; 
			end
			6'h1B: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h6,AD_TABLE6_CFG[47:32]}; 
			end
			6'h1C: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE6_CFG[31:0]; 
			end
			6'h1D: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h5,AD_TABLE5_CFG[47:32]}; 
			end
			6'h1E: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE5_CFG[31:0]; 
			end
			6'h1F: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h4,AD_TABLE4_CFG[47:32]}; 
			end
			6'h20: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE4_CFG[31:0]; 
			end
			6'h21: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h3,AD_TABLE3_CFG[47:32]}; 
			end
			6'h22: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE3_CFG[31:0]; 
			end
			6'h23: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h2,AD_TABLE2_CFG[47:32]}; 
			end
			6'h24: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE2_CFG[31:0]; 
			end
			6'h25: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h1,AD_TABLE1_CFG[47:32]}; 
			end
			6'h26: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE1_CFG[31:0]; 
			end
			6'h27: begin
				axi8b_awaddr <= AD_TABLE1_ADDRESS; 
				axi32b_wdata  <= {16'h0,AD_TABLE0_CFG[47:32]}; 
			end   
			6'h28: begin
				axi8b_awaddr <= AD_TABLE0_ADDRESS; 
				axi32b_wdata  <= AD_TABLE0_CFG[31:0]; 
			end
			6'h29: begin
				axi8b_awaddr <= MDIO_CLK_ADDRESS; 
				axi32b_wdata  <= MDIO_CLK_CFG; 
			end
			6'h2A: begin
				axi8b_awaddr <= MDIO_WE_DATA_ADDRESS; 
				axi32b_wdata  <= MDIO_WE1_DATA_CFG; 
			end
			6'h2B: begin
				axi8b_awaddr <= MDIO_CTRL_ADDRESS; 
				axi32b_wdata  <= MDIO_WE1_CTRL_CFG; 
			end
			6'h2C: begin		//读启动
				axi8b_awaddr <= MDIO_CTRL_ADDRESS; 
				axi32b_wdata  <= MDIO_RD1_CTRL_CFG; 
			end
			default: begin
				axi8b_awaddr <= 8'h0; 
				axi32b_wdata  <= 32'h0; 
			end
		endcase                                                               
	end                                                   
end                                                       
     
//----------------------------
//写响应（b）通道
//----------------------------

//写响应通道提供有关写已提交到内存的反馈。 
// bready将在数据和写入地址都已到达并被从机接受后发生，并可以保证随后没有启动的其他访问。
// bresp位[1]用于指示整个写入突发期间来自互连或从属的任何错误。 本示例将捕获该错误。

always@(posedge mAXI_aclk_i) begin                                                                
	if(mAXI_areset_i == 1 || init_txn_pulse == 1'b1) begin                                                            
		axi_bready <= 1'b0;                                            
	end                                                              
	// 由主控器接受/确认带有axi_bready的信号灯，从机断言m_axi_bvalid                          
	// else if(mAXI_bvalid_i && ~axi_bready) 
	else if(mAXI_awready_i && mAXI_wready_i) begin                                                            
		axi_bready <= 1'b1;                                            
	end                                                              
	// 一个时钟周期后置低                                  
	//else if(axi_bready) 
	else if(mAXI_bvalid_i) begin                                                            
		axi_bready <= 1'b0;                                            
	end                                                              
	// retain the previous value                                       
	else                                                               
		axi_bready <= axi_bready;                                        
end                                                                  
	                                                                       
//flag write errors                                                    
// assign write_resp_error = (axi_bready & mAXI_bvalid_i & mAXI2b_bresp_i[1]);

//=======================================================================
// 读时序
//======================================================================= 
//----------------------------
//读取地址通道
//----------------------------
//start_single_read触发新的读取事务。 
//read_index是一个计数器，用于跟踪 已发出/已发起 的读取事务数

always@(posedge mAXI_aclk_i) begin                                     
	if(mAXI_areset_i == 1 || init_txn_pulse == 1'b1) begin                                                                        
		read6b_index <= 0;                                                           
	end                                                                          
	// 表示用户逻辑提供了新的读取地址                                                     
	else if(start_single_read) begin                                                                        
		read6b_index <= read6b_index + 1;                                              
	end                                                                          
end                                                                              
																																									
// 当主机有一个有效的读取地址时，将声明一个新的axi_arvalid。  
// start_single_read触发新的读取//事务                                                                   
always@(posedge mAXI_aclk_i) begin                                                                            
	if(mAXI_areset_i == 1 || init_txn_pulse == 1'b1) begin                                                                        
		axi_arvalid <= 1'b0;                                                       
	end                                                                          
	//表示用户逻辑可用新的读地址命令                 
	else if(start_single_read) begin                                                                        
		axi_arvalid <= 1'b1;                                                       
	end                                                                          
	//raddress被互连/从设备接受（从设备发出m_axi_arready）    
	else if(mAXI_arready_i && axi_arvalid) begin                                                                        
		axi_arvalid <= 1'b0;                                                       
	end                                                                          
	// retain the previous value            
end                                                                              

//--------------------------------
//读取数据（和响应）通道
//--------------------------------
//读取数据通道返回读取请求的结果.当有有效的读取数据可用时，主机将通过断言axi_rready接受读取数据。

always@(posedge mAXI_aclk_i) begin                                                                 
	if(mAXI_areset_i == 1 || init_txn_pulse == 1'b1) begin                                                             
		axi_rready <= 1'b0;                                             
	end                                                               
	// 主机通过axi_rready接受/确认rdata / rresp ,从机声明m_axi_rvalid                           
	//else if(mAXI_rvalid_i && ~axi_rready) 
	else if(mAXI_arready_i) begin                                                             
		axi_rready <= 1'b1;                                             
	end                                    
	else if(mAXI_rvalid_i) begin                                                             
		axi_rready <= 1'b0;                   
	end                                                               
	// retain the previous value                                        
end                                                                   
	                                                                        
// flag write errors                                                     
// assign read_resp_error = (axi_rready & mAXI_rvalid_i & mAXI2b_rresp_i[1]);  

//--------------------------------
//用户逻辑:读取数据
//--------------------------------
/* 配置地址
TX_ADDRESS = 8'h10
RX_ADDRESS = 8'h20
PAUSE_SRCAD0_ADDRESS = 8'h30
PAUSE_SRCAD1_ADDRESS = 8'h40
SPEED_ADDRESS = 8'h50
FLOW_CTRL_ADDRESS = 8'h60
AD_FILTER_MODE_ADDRESS = 8'h70
UNICAST_AD0_ADDRESS = 8'h80	
UNICAST_AD1_ADDRESS = 8'h82	
AD_TABLE0_ADDRESS = 8'h84
AD_TABLE1_ADDRESS = 8'h86
MDIO_CLK_ADDRESS = 8'h90
MDIO_CTRL_ADDRESS = 8'hA0
MDIO_RD_DATA_ADDRESS = 8'hB0
MDIO_WE_DATA_ADDRESS = 8'hC0
*/

// 根据需要针对不同的地址模式修改它们。
                                          
//read addresses                                              
always@(posedge mAXI_aclk_i) begin                                                     
	if(mAXI_areset_i == 1  || init_txn_pulse == 1'b1) begin                                                 
		axi8b_araddr <= SPEED_ADDRESS;
	end                                                   
	// 表示新的写地址/写数据,可由用户逻辑提供                            
	//else if(mAXI_arready_i && axi_arvalid)
	else if(mAXI_rvalid_i && axi_rready) begin
	  case(read6b_index)
			//6'h00:  axi8b_araddr <= SPEED_ADDRESS;
	    6'h01:  axi8b_araddr <= TX_ADDRESS;
			6'h02:  axi8b_araddr <= RX_ADDRESS;
			6'h03:  axi8b_araddr <= PAUSE_SRCAD0_ADDRESS;
			6'h04:  axi8b_araddr <= PAUSE_SRCAD1_ADDRESS;
			6'h05:  axi8b_araddr <= FLOW_CTRL_ADDRESS;
			6'h06:  axi8b_araddr <= AD_FILTER_MODE_ADDRESS;
			6'h07:  axi8b_araddr <= UNICAST_AD0_ADDRESS;
			6'h08:  axi8b_araddr <= UNICAST_AD1_ADDRESS;
			6'h09:  axi8b_araddr <= AD_TABLE1_ADDRESS;  //读出为最近配置地址表的地址
			6'h0A:  axi8b_araddr <= AD_TABLE0_ADDRESS;
			6'h0B:  axi8b_araddr <= AD_TABLE1_ADDRESS;
			6'h0C:  axi8b_araddr <= AD_TABLE0_ADDRESS;
			6'h0D:  axi8b_araddr <= AD_TABLE1_ADDRESS;
			6'h0E:  axi8b_araddr <= AD_TABLE0_ADDRESS;
			6'h0F:  axi8b_araddr <= AD_TABLE1_ADDRESS; 
			6'h10:  axi8b_araddr <= AD_TABLE0_ADDRESS;
			6'h11:  axi8b_araddr <= MDIO_CLK_ADDRESS; 
			6'h12:  axi8b_araddr <= MDIO_RD_DATA_ADDRESS; 
			default: axi8b_araddr <= 8'h0; 
		endcase    
	end                                                   
end                                                       
																													
always@(posedge mAXI_aclk_i) begin                                                     
	if(mAXI_areset_i == 1  || init_txn_pulse == 1'b1) begin                                                 
		rd32b_data_val <= 32'h0;             
	end                                                   
	// 表示新的写地址/写数据,可由用户逻辑提供                            
	else if(mAXI_rvalid_i && axi_rready) begin                                                 
		rd32b_data_val <= mAXI32b_rdata_i;
	end                                                   
end 
          
//====================================================    
//实现命令接口状态机
//====================================================
	
always@( posedge mAXI_aclk_i) begin                                                                             
	if(mAXI_areset_i == 1 ) begin                                                                         
		// 复位条件
		// 复位条件下所有信号均分配有默认值          
		master2b_state <= IDLE;                                            
		start_single_write <= 1'b0;                                                 
		write_issued <= 1'b0;                                                      
		start_single_read <= 1'b0;                                                 
		read_issued <= 1'b0;
		axi_txn_done_reg <= 1'b0;
	end                 
	else begin                                                                         
		// state transition                                                          
		case(master2b_state)                                                                                                                                
			IDLE:                                                             
			  // 声明 init_txn_pulse 时，此状态负责启动 axi事务 
				if(init_txn_pulse == 1'b1) begin                                                                 
					master2b_state <= INIT_WRITE;
					axi_txn_done_reg    <= 1'b0;
				end                                                                   
				else begin                                                                 
					master2b_state  <= IDLE;                                    
				end                                                                   
																																									
			INIT_WRITE:                                                               
			  // 此状态负责发出start_single_write脉冲以启动写入事务。  
				// 发出写事务，直到断言last_write信号为止。  
				// 写控制器                                                     
				if(writes_done) begin                                                                 
					master2b_state <= INIT_READ;                                     
				end                                                                   
				else begin                                                                 
					master2b_state  <= INIT_WRITE;                                                                                                      
					if(~axi_awvalid && ~axi_wvalid && ~mAXI_bvalid_i && ~mAXI_bready_o && ~last_write && ~start_single_write && ~write_issued)
						//if(mAXI_bvalid_i && ~last_write && ~start_single_write && ~write_issued)
						begin                                                           
							start_single_write <= 1'b1;                                   
							write_issued  <= 1'b1;                                        
						end                                                             
					//else if(axi_bready)
					else if(mAXI_bvalid_i) 
					  begin                                                           
						  write_issued  <= 1'b0;                                        
					  end                                                             
					else begin                                                           
							start_single_write <= 1'b0; //negate to generate a pulse      
					end                                                             
				end                                                                   
																																									
			INIT_READ:                                                                
				// 此状态负责发出start_single_read脉冲以启动读取事务。  
				// 发出读事务，直到断言last_read信号为止。                           
				// read controller                                                     
				if(reads_done) begin                                                                
					master2b_state <= IDLE;
					axi_txn_done_reg <= 1'b1;
				end                                                                  
				else begin                                                                
					master2b_state  <= INIT_READ;                                      
																																	
					if(~axi_arvalid && ~mAXI_rvalid_i && ~axi_rready && ~last_read && ~start_single_read && ~read_issued)
						begin                                                            
							start_single_read <= 1'b1;                                     
							read_issued  <= 1'b1;                                          
						end      
					//else if(axi_rready) 
					else if(mAXI_rvalid_i)
						begin                                                            
							read_issued  <= 1'b0;                                          
						end                                                              
					else                                                               
						begin                                                            
							start_single_read <= 1'b0; //negate to generate a pulse        
						end                                                              
				end                                                                  
																																																															
			default :                                                                
				begin                                                                  
					master2b_state  <= IDLE;                                     
				end                                                                    
		endcase                                                                     
	end                                                                             
end		//master_execution_proc                                                       
	                                                                                    
	//终端写入次数                                                            
	                                                                                    
always@(posedge mAXI_aclk_i) begin                                                                             
	if(mAXI_areset_i == 1  || init_txn_pulse == 1'b1)                                                         
		last_write <= 1'b0;    
		//最后一次写入应与写入地址就绪响应相关联       
	else if((write6b_index == WE_TRANSACTIONS_NUM) && mAXI_awready_i)    //transactions_num值比 case(write6b_index)值加1            
		last_write <= 1'b1;                                                           
	else                                                                            
		last_write <= last_write;                                                     
end                                                                               
	                                                                                    
//检查最后的写入完成                                              
//此逻辑是用最后的写入响应来限定最后的写入计数。 这演示了如何确认是否已提交写入                                                                     
																																									
always@(posedge mAXI_aclk_i) begin                                                                             
	if(mAXI_areset_i == 1  || init_txn_pulse == 1'b1)                                                         
		writes_done <= 1'b0;                                                                                                                                     
		//the writes_done should be associated with a bready response                 
	else if(last_write && mAXI_bvalid_i && axi_bready)                              
		writes_done <= 1'b1;                                                          
	else                                                                            
		writes_done <= writes_done;                                                   
end                                                                               
	                                                                                    
//------------------                                                                
//read example                                                                      
//------------------                                                                
//终端读取计数                                                               
																																										
always@(posedge mAXI_aclk_i) begin                                                                             
	if(mAXI_areset_i == 1  || init_txn_pulse == 1'b1)                                                         
		last_read <= 1'b0;                                                            
																																									
	//最后读取应与读取地址就绪响应相关联         
	else if((read6b_index == RD_TRANSACTIONS_NUM) && (mAXI_arready_i) )        // RD_TRANSACTIONS_NUM 值 比 case(read6b_index) 值加1      
		last_read <= 1'b1;                                                            
	else                                                                            
		last_read <= last_read;                                                       
end                                                                               
																																										
/*                                                                                  
检查最后的读取完成                                               
该逻辑是用最终的读取响应/数据来限定最后的读取计数。                                                                     
*/                                                                                 
always@(posedge mAXI_aclk_i) begin                                                                             
	if(mAXI_areset_i == 1 || init_txn_pulse == 1'b1)                                                         
		reads_done <= 1'b0;                                                                                                                                       
	//reads_done应该与已读响应相关联                
	else if(last_read && mAXI_rvalid_i && axi_rready)                               
		reads_done <= 1'b1;                                                           
	else                                                                            
		reads_done <= reads_done;                                                     
end                                                                           

endmodule